<?php

/**
 * Security object handles authenticating users & session handling, plus restoring auth/session states
 *
 * @todo Need to refactor any methods that call mysql_*
 * @author Ben Rowe
 */
class Security
{
	
	/**
	 * Validation status
	 *
	 * @access private
	 * @var boolean
	 */
	var $_authenticated = false;
	
	
	/**
	 * Stores the details of the authenticated user as an array. If no one is authenticated, then this stores a boolean false
	 *
	 * @access private
	 * @var array when authenticated, otherwise false
	 */
	var $_details = false;
	
	/**
	 * Store an array of permission strings that the current user has available
	 *
	 * @access private
	 * @var array
	 */
	var $_permissions = array();
	
	/**
	 * Constructor
	 *
	 * @access public
	 * @return Security
	 */
	function Security()
	{
		if(session_start()) {
			$this->_restoreState();
		} else {
			die('unable to start session');
		}
	}
	
	/**
	 * Get the authentication state of this user
	 *
	 * @access public
	 * @return boolean
	 */
	function isAuthenticated()
	{
		return $this->_authenticated;
	}
	
	/**
	 * Retrieve the stored details of the authenticated user
	 *
	 * @access public
	 * @return array
	 */
	function getUserDetails()
	{
		return $this->_details;
	}
	
	/**
	 * Mark the current user id as being valid & successfully authenticated
	 *
	 * @access public
	 * @return boolean true on successful authentication
	 */
	function authenticated($user_id)
	{
		$this->_authenticated = true;
		$_SESSION['authenticated'] = true;
		$_SESSION['user_id'] = (int)$user_id;
		$this->_setLastLogin();
		$this->_restoreState();
		return true;
	}
	
	/**
	 * Set the last action date for the current user
	 *
	 * @access private
	 * @return boolean
	 */
	function _setLastLogin()
	{
		$sql	= "UPDATE `administrators` SET `date_last_login` = UNIX_TIMESTAMP() WHERE `id` = ".$_SESSION['user_id'];
		$result	= mysql_query($sql);
		return true;
	}
	
	/**
	 * Set the last logout date for the current user
	 *
	 * @access private
	 * @return boolean
	 */
	function _setLastLogout()
	{
		$sql	= "UPDATE `administrators` SET `date_last_logout` = UNIX_TIMESTAMP() WHERE `id` = ".$_SESSION['user_id'];
		$result	= mysql_query($sql);
		return true;
	}
	
	/**
	 * Set the last login date for the current user
	 *
	 * @access private
	 * @return boolean
	 */
	function _setLastAction()
	{
		$sql	= "UPDATE `administrators` SET `date_last_action` = UNIX_TIMESTAMP() WHERE `id` = ".$_SESSION['user_id'];
		$result	= mysql_query($sql);
		return true;
	}
	
	/**
	 * Remove the authenticated state from the security object!
	 * 
	 * @access public
	 * @return boolean true on success deauthenticate
	 */
	function deauthenticate()
	{
		$this->_setLastLogout();
		$this->_authenticated = false;
		$_SESSION['authenticated'] = false;
		$_SESSION['user_id'] = false;
		unset($_SESSION['authenticated'], $_SESSION['user_id']);
		return true;
	}
	
	/**
	 * Restore the state of the security object
	 *
	 * @access private
	 * @return boolean
	 */
	function _restoreState()
	{
		// if the session data is authenticated, or the object is already authenticated, otherwise dont retrieve any details!
		if((array_key_exists('authenticated', $_SESSION) && $_SESSION['authenticated'] === true) || $this->_authenticated === true) {
			// attempt to get the users details!
			$user_id = isset($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : 0;
			$sql	= "SELECT `a`.`id`, `a`.`username`, `a`.`email_address`, `p`.`permissions` FROM `administrators` `a` INNER JOIN `permissions` `p` ON `a`.`permission_id` = `p`.`id` WHERE `a`.`id` = ".$user_id." AND `a`.`active` = 1";
			$result	= mysql_query($sql) or die(mysql_error());
			if(mysql_num_rows($result) == 1) {
				$this->_authenticated = true;
				$this->_setLastAction();
				$details = mysql_fetch_assoc($result);
				$this->_permissions = $this->_processPermissions($details['permissions']);
				unset($details['permissions']);
				$this->_details = $details;
				return true;
			}
		} else {
			// reset the state to blank!
			$this->_details = false;
			$this->_permissions = array();
			$this->_authenticated = false;
		}
		return true;
	}
	
	/**
	 * Check if the permission is currently availble for the current logged in administrator
	 *
	 * @access public
	 * @param mixed $permission permission string, or array of permission strings
	 * @return boolean true on has permission
	 */
	function hasPermission($permission)
	{
		if($this->_authenticated) {
			if(!is_array($permission)) $permission = array($permission);
			foreach($permission as $p) {
				if(in_array($p, $this->_permissions)) {
					return true; 
				}
			}
		}
		return false;
	}
	
	
	/**
	 * Pricess the permissions string into an array
	 *
	 * @access private
	 * @param string $permissions
	 * @return array
	 */
	function _processPermissions($permissions)
	{
		$perms = array();
		if(!empty($permissions)) {
			$perms = preg_split("/(\n|\r+)/", $permissions);
		}
		return $perms;	
	}
}

?>